#include "EpilRecordFieldParser.h"
#include "EpilParserException.h"
#include "EpilExpressionParser.h"
#include "EpilFieldIndexInitializerCode.h"
#include "EpilFieldKeyInitializerCode.h"
#include "EpilIndexParser.h"
#include "EpilPointerHelper.h"


EpilRecordFieldParser::EpilRecordFieldParser( EpilTokenStream & tokens )
: EpilSyntaxParserBase( tokens )
{
}


void EpilRecordFieldParser::Parse()
{
	// recfield -> (NAME | `['exp1`]') = exp1
	if( this->GetTokens().GetCurrentToken().type == ETT_Identifier )
	{
		EpilFieldKeyInitializerCode * stringInitializer = new EpilFieldKeyInitializerCode( this->GetTokens().GetCurrentToken().location );
		stringInitializer->SetKey( this->GetTokens().GetCurrentToken().text );
		m_initializer = stringInitializer;
		this->GetTokens().MoveToNext();
	}
	else
	{
		EpilFieldIndexInitializerCode * indexInitializer = new EpilFieldIndexInitializerCode( this->GetTokens().GetCurrentToken().location );
		
		EpilIndexParser indexParser( this->GetTokens() );
		try
		{
			indexParser.Parse();
		}
		catch( ... )
		{
			EpilPointerHelper::SafeDelete( indexInitializer );
			throw;
		}
		indexInitializer->SetIndexExpression( indexParser.GetIndexExpression() );
		m_initializer = indexInitializer;
	}

	if( this->GetTokens().GetCurrentToken().type != ETT_OpAssign )
	{
		EpilPointerHelper::SafeDelete( m_initializer );
		throw EpilParserException( t("\'=\' expected."), this->GetTokens().GetCurrentToken().location );
	}
	this->GetTokens().MoveToNext();

	EpilExpressionParser exprParser( this->GetTokens() );
	try
	{
		exprParser.Parse();
	}
	catch( ... )
	{
		EpilPointerHelper::SafeDelete( m_initializer );
		throw;
	}
	m_initializer->SetExpression( exprParser.GetExpression() );
}